/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package se.sll.engagemangsindex.task;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.ws.BindingProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import se.sll.engagemangsindex.ejb.LogicalAddressCache;
import skl.tp.vagvalsinfo.v1.*;

/**
 *
 * @author khaleddaham
 */
@Stateless
public class LogicalAddressesTask {

    private static final Logger LOG = (Logger) LoggerFactory.getLogger(LogicalAddressesTask.class);
    @Inject
    private LogicalAddressCache logicalCache;
    private SokVagvalsInfoInterface sokVagVal = null;
    private BindingProvider bp = null;
    private String requestReceiverId = "1";
    private String contract = "urn:riv:itintegration:engagementindex:ReceiveNotification:1";
    private String senderId = "2";

    /**
     * Setup service
     */
    public LogicalAddressesTask() throws MalformedURLException {
        //final URL url = new URL( SokVagvalsServiceSoap11LitDocService.class.getResource( SokVagvalsServiceSoap11LitDocService.class.getSimpleName() + ".class"), "/META-INF/wsdl/wrapped-vagvalsinfo-sokvagvalsinfo-1.0.wsdl");
        SokVagvalsServiceSoap11LitDocService service = new SokVagvalsServiceSoap11LitDocService();
        sokVagVal = service.getSokVagvalsSoap11LitDocPort();
        bp = (BindingProvider) sokVagVal;
    }

    public LogicalAddressesTask(SokVagvalsServiceSoap11LitDocService service) {
        sokVagVal = service.getSokVagvalsSoap11LitDocPort();
        bp = (BindingProvider) sokVagVal;
    }

    /**
     * @TODO filter contracts so we only get the ones we must have
     *
     * @param endpointURL
     */
    public void cacheLogicalAddresses(String endpointURL) {
        bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointURL);
        try {
            HamtaAllaVirtualiseringarResponseType respAllaVirtualiseringar = sokVagVal.hamtaAllaVirtualiseringar(null);
            List<VirtualiseringsInfoType> virtualiseringsInfoList = respAllaVirtualiseringar.getVirtualiseringsInfo();
            List<String> addressList = new ArrayList<String>();
            HamtaAllaAnropsBehorigheterResponseType callAuthInfo = sokVagVal.hamtaAllaAnropsBehorigheter(null);

            for (VirtualiseringsInfoType info : virtualiseringsInfoList) {
                if (info.getTjansteKontrakt().equals(this.contract)) {
                    if (checkAuthorization(info, callAuthInfo.getAnropsBehorighetsInfo())) {
                        addressList.add(info.getAdress());
                    }
                }
            }
            logicalCache.updateCache(addressList);
        } catch (Exception ex) {
            LOG.error("Failed to retrieve logical addresses from service catalogue", ex);
        }
    }

    protected boolean checkAuthorization(VirtualiseringsInfoType info, List<AnropsBehorighetsInfoType> anropsBehorighetsInfo) {
        for (AnropsBehorighetsInfoType abi : anropsBehorighetsInfo) {
            if (abi.getReceiverId().equals(this.requestReceiverId)
                    && abi.getSenderId().equals(this.senderId)
                    && abi.getTjansteKontrakt().equals(this.contract)
                    && this.getTidpunkt().compare(abi.getFromTidpunkt()) != DatatypeConstants.LESSER
                    && this.getTidpunkt().compare(abi.getTomTidpunkt()) != DatatypeConstants.GREATER) {
                LOG.info("Authorization granted for: " + info.getTjansteKontrakt());
                return true;
            }
        }
        LOG.info("Authorization NOT granted for: " + info.getTjansteKontrakt());
        return false;
    }

    /**
     *
     * @param cache
     */
    protected void setLogicalAddressCache(LogicalAddressCache cache) {
        this.logicalCache = cache;
    }

    /**
     *
     * @param sokVagVal
     */
    protected void setSokVagVal(SokVagvalsInfoInterface sokVagVal) {
        this.sokVagVal = sokVagVal;
    }

    /**
     *
     * @return
     */
    private XMLGregorianCalendar getTidpunkt() {
        GregorianCalendar now = (GregorianCalendar) GregorianCalendar.getInstance();
        XMLGregorianCalendar xmlNow;
        try {
            xmlNow = DatatypeFactory.newInstance().newXMLGregorianCalendar(now);
        } catch (DatatypeConfigurationException e) {
            throw new RuntimeException(
                    "Creation of XMLGregorianCalendar failed", e);
        }
        return xmlNow;
    }

    void setBindingProvider(BindingProvider mockBindingProvider) {
        this.bp = mockBindingProvider;
    }
}